package com.rengwuxian.coursecoroutines._3_scope_context

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.coroutineContext

/**
 * 从挂起函数里获取CoroutineContext
 * coroutineContext、currentCoroutineContext()
 *
 * ContinuationInterceptor 就是 Dispatcher
 * 挂起函数一定在协程中运行的(拿coroutineContext是合情合理的)，所以一定有CoroutineScope，那就一定有coroutineContext了
 *
 * 挂起函数中，不需要CoroutineScope也能拿到coroutineContext了，协程做了一个特殊处理。suspend了一个coroutineContext，可以直接导入使用.
 * currentCoroutineContext() == coroutineContext（可以拿到的）
 * currentCoroutineContext是用来避免命名冲突的。
 * 比如launch中有一个flow，flow的（参数是suspend类型）collect中拿到coroutineContext就是launch的receiver，flow中就不能使用，需要使用currentCoroutineContext()
 * 本示例中可以看到。
 * 想用哪个，用哪个，避免命名冲突，选择currentCoroutineContext()    隐式的Receiver中
 * 属于协程的紧急修复，记住它的特殊点。
 */
fun main() = runBlocking<Unit> {
  val scope = CoroutineScope(EmptyCoroutineContext)
  scope.launch {
    showDispatcher()
  }
  delay(10000)
}

private fun flowFun() {
  flow<String> {
    coroutineContext
  }
  GlobalScope.launch {
    flow<String> {
      currentCoroutineContext()
    }
  }
}

private suspend fun showDispatcher() {
  delay(1000)
  println("Dispatcher: ${coroutineContext[ContinuationInterceptor]}")
}